"use client"

import { zodResolver } from "@hookform/resolvers/zod"
import {
  AlertTriangleIcon,
  ChevronDownIcon,
  DownloadIcon,
  GitBranchIcon,
  MoreHorizontal,
  PlayIcon,
  SaveIcon,
  SquarePlay,
  WorkflowIcon,
} from "lucide-react"
import Link from "next/link"
import { usePathname } from "next/navigation"
import React from "react"
import { useForm } from "react-hook-form"
import YAML from "yaml"
import { z } from "zod"
import type { ValidationResult } from "@/client"
import { ApiError } from "@/client"
import { CodeEditor } from "@/components/editor/codemirror/code-editor"
import { ExportMenuItem } from "@/components/export-workflow-dropdown-item"
import { Spinner } from "@/components/loading/spinner"
import { Badge } from "@/components/ui/badge"
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Button } from "@/components/ui/button"
import { Dialog } from "@/components/ui/dialog"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
import { ValidationErrorView } from "@/components/validation-errors"
import { useFeatureFlag } from "@/hooks/use-feature-flags"
import { useWorkspaceDetails } from "@/hooks/use-workspace"
import type { TracecatApiError } from "@/lib/errors"
import {
  useCreateManualWorkflowExecution,
  useOrgAppSettings,
} from "@/lib/hooks"
import { cn } from "@/lib/utils"
import { useWorkflowBuilder } from "@/providers/builder"
import { useWorkflow } from "@/providers/workflow"
import { useWorkspaceId } from "@/providers/workspace-id"

export function BuilderNav() {
  const {
    workflow,
    isLoading: workflowLoading,
    commitWorkflow,
    publishWorkflow,
    validationErrors,
    setValidationErrors,
  } = useWorkflow()

  const workspaceId = useWorkspaceId()
  const { workspace, workspaceLoading } = useWorkspaceDetails()

  const handleCommit = async () => {
    console.log("Saving changes...")
    try {
      const response = await commitWorkflow()
      const { status, errors } = response
      if (status === "failure") {
        setValidationErrors(errors || null)
      } else {
        setValidationErrors(null)
      }
    } catch (error) {
      console.error("Failed to save workflow:", error)
    }
  }

  if (!workflow || workflowLoading || !workspace || workspaceLoading) {
    return null
  }

  const manualTriggerDisabled = workflow.version === null

  return (
    <div className="flex w-full items-center">
      <div className="mr-4 min-w-0 flex-1">
        <Breadcrumb>
          <BreadcrumbList className="flex-nowrap overflow-hidden whitespace-nowrap">
            <BreadcrumbItem>
              <BreadcrumbLink asChild>
                <Link href={`/workspaces/${workspaceId}/workflows`}>
                  {workspace.name}
                </Link>
              </BreadcrumbLink>
            </BreadcrumbItem>
            <BreadcrumbSeparator className="shrink-0 font-semibold">
              {"/"}
            </BreadcrumbSeparator>
            <BreadcrumbItem>
              <span>{workflow.title}</span>
              {workflow.alias && (
                <Badge
                  variant="secondary"
                  className="font-mono text-xs font-normal tracking-tighter text-muted-foreground hover:cursor-default"
                >
                  {workflow.alias}
                </Badge>
              )}
            </BreadcrumbItem>
          </BreadcrumbList>
        </Breadcrumb>
      </div>

      <div className="flex items-center justify-end space-x-6">
        {/* Workflow tabs */}
        <TabSwitcher workflowId={workflow.id} />
        {/* Workflow manual trigger */}

        <WorkflowManualTrigger
          disabled={manualTriggerDisabled}
          workflowId={workflow.id}
        />
        {/* Save button */}
        <WorkflowSaveActions
          workflow={workflow}
          validationErrors={validationErrors}
          onSave={handleCommit}
          onPublish={publishWorkflow}
        />

        {/* Workflow options */}
        <BuilderNavOptions workspaceId={workspaceId} workflowId={workflow.id} />
      </div>
    </div>
  )
}

function TabSwitcher({ workflowId }: { workflowId: string }) {
  const pathname = usePathname()
  const workspaceId = useWorkspaceId()
  let leafRoute: string = "workflow"
  if (pathname && pathname.includes("executions")) {
    leafRoute = "executions"
  }

  const builderPath = `/workspaces/${workspaceId}/workflows/${workflowId}`

  return (
    <Tabs value={leafRoute}>
      <TabsList className="grid h-8 w-full grid-cols-2">
        <TabsTrigger
          className="w-full px-2 py-0 after:content-none"
          value="workflow"
          asChild
        >
          <Link href={builderPath} className="size-full text-xs" passHref>
            <WorkflowIcon className="mr-2 size-4" />
            <span>Workflow</span>
          </Link>
        </TabsTrigger>
        <TabsTrigger
          className="w-full px-2 py-0 after:content-none"
          value="executions"
          asChild
        >
          <Link
            href={`${builderPath}/executions`}
            className="size-full text-xs"
            passHref
          >
            <SquarePlay className="mr-2 size-4" />
            <span>Runs</span>
          </Link>
        </TabsTrigger>
      </TabsList>
    </Tabs>
  )
}

const workflowControlsFormSchema = z.object({
  payload: z.string().superRefine((val, ctx) => {
    try {
      JSON.parse(val)
    } catch (error) {
      if (error instanceof Error) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: `Invalid JSON format: ${error.message}`,
        })
      } else {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "Invalid JSON format: Unknown error occurred",
        })
      }
    }
  }),
})
type TWorkflowControlsForm = z.infer<typeof workflowControlsFormSchema>

const publishFormSchema = z.object({
  message: z.string().optional(),
})
type TPublishForm = z.infer<typeof publishFormSchema>

function WorkflowManualTrigger({
  disabled = true,
  workflowId,
}: {
  disabled: boolean
  workflowId: string
}) {
  const { expandSidebarAndFocusEvents, setCurrentExecutionId } =
    useWorkflowBuilder()
  const { createExecution, createExecutionIsPending } =
    useCreateManualWorkflowExecution(workflowId)
  const [open, setOpen] = React.useState(false)
  const [lastTriggerInput, setLastTriggerInput] = React.useState<string | null>(
    null
  )
  const [manualTriggerErrors, setManualTriggerErrors] = React.useState<Record<
    string,
    string
  > | null>(null)
  const [isTriggering, setIsTriggering] = React.useState(false)
  const form = useForm<TWorkflowControlsForm>({
    resolver: zodResolver(workflowControlsFormSchema),
    defaultValues: {
      payload:
        lastTriggerInput ||
        JSON.stringify({ sampleWebhookParam: "sampleValue" }, null, 2),
    },
  })

  const runWorkflow = async ({ payload }: Partial<TWorkflowControlsForm>) => {
    if (disabled || createExecutionIsPending) return
    setIsTriggering(true)
    setTimeout(() => setIsTriggering(false), 1000)
    setManualTriggerErrors(null)
    try {
      const result = await createExecution({
        workflow_id: workflowId,
        inputs: payload ? JSON.parse(payload) : undefined,
      })

      // Store the execution ID directly
      if (result && result.wf_exec_id) {
        setCurrentExecutionId(result.wf_exec_id)
      }

      // Expand sidebar immediately
      expandSidebarAndFocusEvents()
    } catch (error) {
      if (error instanceof ApiError) {
        const tracecatError = error as TracecatApiError<Record<string, string>>
        console.error("Error details", tracecatError.body.detail)
        setManualTriggerErrors(tracecatError.body.detail)
      }
    }
  }

  const runWithPayload = async ({ payload }: TWorkflowControlsForm) => {
    // Make the API call to start the workflow
    setLastTriggerInput(payload)
    try {
      await runWorkflow({ payload })
    } finally {
      setOpen(false)
    }
  }

  const executionPending = createExecutionIsPending || isTriggering
  return (
    <Form {...form}>
      <div
        className={cn(
          "flex h-7 divide-x rounded-lg border border-input overflow-hidden",
          manualTriggerErrors
            ? "divide-white/30 dark:divide-black/30"
            : "divide-white/20 dark:divide-black/40"
        )}
      >
        {/* Main Button */}
        <Button
          type="button"
          variant={manualTriggerErrors ? "destructive" : "default"}
          className="h-full gap-2 rounded-r-none border-none px-3 py-0 text-xs"
          disabled={disabled || executionPending}
          onClick={() => runWorkflow({ payload: undefined })}
        >
          {executionPending ? (
            <Spinner className="size-3" segmentColor="currentColor" />
          ) : manualTriggerErrors ? (
            <AlertTriangleIcon className="size-3" />
          ) : (
            <PlayIcon className="size-3" />
          )}
          <span>Run</span>
        </Button>
        {/* Dropdown Button */}
        <Tooltip delayDuration={500}>
          <Popover
            open={open && !disabled}
            onOpenChange={(newOpen) => !disabled && setOpen(newOpen)}
          >
            <TooltipTrigger asChild>
              <PopoverTrigger asChild>
                <Button
                  type="button"
                  variant={manualTriggerErrors ? "destructive" : "default"}
                  className="h-full w-7 rounded-l-none border-none px-1 py-0 text-xs font-bold"
                  disabled={disabled || executionPending}
                >
                  <ChevronDownIcon className="size-3" />
                </Button>
              </PopoverTrigger>
            </TooltipTrigger>
            <PopoverContent className="w-fit max-w-xl p-3 sm:max-w-2xl">
              <form onSubmit={form.handleSubmit(runWithPayload)}>
                <div className="flex h-fit flex-col">
                  <span className="mb-2 text-xs text-muted-foreground">
                    Edit the JSON payload below.
                  </span>
                  <FormField
                    control={form.control}
                    name="payload"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          <CodeEditor
                            value={field.value}
                            language="json"
                            onChange={field.onChange}
                            className="[&_.cm-editor]:!border [&_.cm-editor]:!border-input [&_.cm-editor]:!bg-background [&_.cm-editor]:rounded-md [&_.cm-scroller]:max-h-96 [&_.cm-scroller]:overflow-auto [&_.cm-scroller]:h-auto sm:[&_.cm-scroller]:max-h-[500px]"
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                  <Button
                    type="submit"
                    variant="default"
                    disabled={executionPending}
                    className="group mt-2 flex h-7 items-center px-3 py-0 text-xs"
                  >
                    {executionPending ? (
                      <Spinner
                        className="mr-2 size-3"
                        segmentColor="currentColor"
                      />
                    ) : (
                      <PlayIcon className="mr-2 size-3" />
                    )}
                    <span>{executionPending ? "Starting..." : "Run"}</span>
                  </Button>
                </div>
              </form>
            </PopoverContent>
          </Popover>
          <TooltipContent
            side="bottom"
            className={cn("text-xs shadow-lg", manualTriggerErrors && "p-0")}
          >
            {manualTriggerErrors ? (
              <div className="space-y-2 overflow-auto rounded-md border border-rose-400 bg-rose-100 p-2 font-mono tracking-tighter">
                <span className="text-xs font-bold text-rose-500">
                  Trigger Validation Errors
                </span>
                <div className="mt-1 space-y-1">
                  <pre className="text-wrap text-rose-500">
                    {YAML.stringify(manualTriggerErrors)}
                  </pre>
                </div>
              </div>
            ) : disabled ? (
              "Please save changes to enable manual trigger."
            ) : executionPending ? (
              "Starting workflow execution..."
            ) : (
              "Run the workflow with trigger inputs."
            )}
          </TooltipContent>
        </Tooltip>
      </div>
    </Form>
  )
}

function WorkflowSaveActions({
  workflow,
  validationErrors,
  onSave,
  onPublish,
}: {
  workflow: { version?: number | null }
  validationErrors: ValidationResult[] | null
  onSave: () => Promise<void>
  onPublish: (params: { message?: string }) => Promise<void>
}) {
  const { isFeatureEnabled } = useFeatureFlag()
  const [publishOpen, setPublishOpen] = React.useState(false)
  const [isPublishing, setIsPublishing] = React.useState(false)

  const publishForm = useForm<TPublishForm>({
    resolver: zodResolver(publishFormSchema),
    defaultValues: {
      message: "",
    },
  })

  const handlePublish = async (data: TPublishForm) => {
    setIsPublishing(true)
    try {
      await onPublish({ message: data.message || undefined })
    } finally {
      setIsPublishing(false)
      setPublishOpen(false)
      publishForm.reset()
    }
  }

  const isGitSyncEnabled = isFeatureEnabled("git-sync")

  return (
    <div className="flex items-center space-x-2">
      <div className="flex h-7 gap-px rounded-lg border border-input">
        {/* Main Save Button */}
        <ValidationErrorView
          side="bottom"
          validationErrors={validationErrors || []}
          noErrorTooltip={
            <span>
              Save workflow v{(workflow.version || 0) + 1} with your changes.
            </span>
          }
        >
          <Button
            variant="outline"
            onClick={onSave}
            className={cn(
              "h-full border-none px-3 py-0 text-xs text-muted-foreground",
              isGitSyncEnabled ? "rounded-r-none" : "rounded-lg",
              validationErrors &&
                "border-rose-400 text-rose-400 hover:bg-transparent hover:text-rose-500"
            )}
          >
            {validationErrors ? (
              <AlertTriangleIcon className="mr-2 size-4 fill-red-500 stroke-white" />
            ) : (
              <SaveIcon className="mr-2 size-4" />
            )}
            Save
          </Button>
        </ValidationErrorView>

        {/* Dropdown Button - Only show if git-sync is enabled */}
        {isGitSyncEnabled && (
          <DropdownMenu open={publishOpen} onOpenChange={setPublishOpen}>
            <DropdownMenuTrigger asChild>
              <Button
                variant="outline"
                className="h-full w-7 rounded-l-none border-none px-1 py-0 text-xs text-muted-foreground"
              >
                <ChevronDownIcon className="size-3" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-96 p-3">
              <Form {...publishForm}>
                <form
                  onSubmit={publishForm.handleSubmit(handlePublish)}
                  className="flex flex-col"
                >
                  <span className="mb-2 text-xs text-muted-foreground">
                    Commit workflow
                  </span>
                  <FormField
                    control={publishForm.control}
                    name="message"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          <Input
                            {...field}
                            placeholder="Add a short description of your changes (optional)"
                            className="h-7 px-3 text-xs"
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                  <Button
                    type="submit"
                    disabled={isPublishing}
                    className="mt-2 flex h-7 w-full items-center justify-center gap-2 bg-primary px-3 py-0 text-xs text-white hover:bg-primary/80"
                  >
                    {isPublishing ? (
                      <>
                        <Spinner className="size-3" />
                        Publishing changes...
                      </>
                    ) : (
                      <>
                        <GitBranchIcon className="size-3" />
                        Publish changes
                      </>
                    )}
                  </Button>
                </form>
              </Form>
            </DropdownMenuContent>
          </DropdownMenu>
        )}
      </div>

      <Badge
        variant="secondary"
        className="h-7 text-xs font-normal text-muted-foreground hover:cursor-default"
      >
        {workflow.version ? `v${workflow.version}` : "Draft"}
      </Badge>
    </div>
  )
}

function BuilderNavOptions({
  workspaceId,
  workflowId,
}: {
  workspaceId: string
  workflowId: string
}) {
  const { appSettings } = useOrgAppSettings()
  const enabledExport = appSettings?.app_workflow_export_enabled
  return (
    <Dialog>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="ghost" size="icon">
            <MoreHorizontal className="size-4" />
            <span className="sr-only">More</span>
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <ExportMenuItem
            enabledExport={enabledExport}
            format="yaml"
            workspaceId={workspaceId}
            workflowId={workflowId}
            icon={<DownloadIcon className="mr-2 size-4" />}
          />
          <ExportMenuItem
            enabledExport={enabledExport}
            format="json"
            workspaceId={workspaceId}
            workflowId={workflowId}
            icon={<DownloadIcon className="mr-2 size-4" />}
          />
        </DropdownMenuContent>
      </DropdownMenu>
    </Dialog>
  )
}
